﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows.Media.Animation;

using Core;
using Core.Primitives;

namespace FrontEnd
{
    /// <summary>
    /// Interaction logic for DataFieldPresenter.xaml
    /// </summary>
    public partial class DataFieldPresenter : UserControl
    {
        private Color[] m_colors = new[] { Colors.Red, Colors.Green, Colors.Blue, Colors.Orange, Colors.CornflowerBlue };

        private SingleRect m_boundingRectangle;
        public SingleRect BoundingRectangle
        {
            get { return m_boundingRectangle; }
            set { m_boundingRectangle = value; }
        }
        
        public IEnumerable<SinglePolyline> Contours
        {
            get { return (IEnumerable<SinglePolyline>)GetValue(ContoursProperty); }
            set { SetValue(ContoursProperty, value); }
        }
        public static readonly DependencyProperty ContoursProperty = DependencyProperty.Register("Contours", typeof(IEnumerable<SinglePolyline>), typeof(DataFieldPresenter), new UIPropertyMetadata(null, OnContoursChanged));
        private static void OnContoursChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DataFieldPresenter p = (DataFieldPresenter)d;

            p.PresentContours();
        }

        public DataFieldPresenter()
        {
            InitializeComponent();
        }

        private Point ToScreenCoordinate(SinglePoint p)
        {
            double x = (p.X - m_boundingRectangle.Left) / m_boundingRectangle.Width * MainCanvas.ActualWidth;
            double y = (p.Y - m_boundingRectangle.Bottom) / m_boundingRectangle.Height * MainCanvas.ActualHeight;
            
            return new Point(x, y);
        }        
        private void PresentContours()
        {
            if (Contours == null)
                return;            

            MainCanvas.Children.Clear();

            foreach (var contour in Contours)
            {
                AddRegion(MainCanvas, contour, m_colors[contour.Type]);
            }
        }
        private void AddRegion(Canvas canvas, SinglePolyline contour, Color color)
        {
            PointCollection points = new PointCollection(contour.Points.Length);

            for (int i = 0; i < contour.Points.Length; i++)
                points.Add(ToScreenCoordinate(contour.Points[i]));

            Polygon coloredPoly = new Polygon()
            {
                Fill = new SolidColorBrush(Color.FromArgb(255, color.R, color.G, color.B)),                
                Points = points,
                Style = (Style)Resources["RegionStyle2"]
            };

            #region Variable contours stroke thickness
            Binding b = new Binding()
                {
                    Source = CanvasScaleTransform,
                    Path = new PropertyPath(ScaleTransform.ScaleXProperty),
                    Converter = new MultiplierValueConverter(2, true)
                };
            coloredPoly.SetBinding(Polygon.StrokeThicknessProperty, b); 
            #endregion

            canvas.Children.Add(coloredPoly);
        }
        private void MainCanvas_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            PresentContours();
        }
        private void UserControl_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            const float scaleFactor = 1.10f;
            //const float animationDirationMs = 200;

            Point rawMousePosition = Mouse.GetPosition(MainCanvas);

            //ScaleTransform inverseTransform = new ScaleTransform()
            //{
            //    CenterX = CanvasScaleTransform.CenterX,
            //    CenterY = CanvasScaleTransform.CenterY,
            //    ScaleX = 1 / CanvasScaleTransform.ScaleX,
            //    ScaleY = 1 / CanvasScaleTransform.ScaleY
            //};

            //Point transformedMousePosition = inverseTransform.Transform(rawMousePosition);
            Point transformedMousePosition = rawMousePosition;

            double newScale;

            if (e.Delta > 0) // zooming in
            {
                newScale = CanvasScaleTransform.ScaleX * scaleFactor;                
            }
            else // zooming out
            {
                newScale = CanvasScaleTransform.ScaleX / scaleFactor;
                newScale = newScale < 1 ? 1 : newScale;
            }

            //DoubleAnimation xCenterAnimation = new DoubleAnimation(transformedMousePosition.X, new Duration(TimeSpan.FromMilliseconds(animationDirationMs)));
            //DoubleAnimation yCenterAnimation = new DoubleAnimation(transformedMousePosition.Y, new Duration(TimeSpan.FromMilliseconds(animationDirationMs)));
            //DoubleAnimation scaleAnimation = new DoubleAnimation(newScale, new Duration(TimeSpan.FromMilliseconds(animationDirationMs)));

            //CanvasScaleTransform.BeginAnimation(ScaleTransform.CenterXProperty, xCenterAnimation);
            //CanvasScaleTransform.BeginAnimation(ScaleTransform.CenterYProperty, yCenterAnimation);
            //CanvasScaleTransform.BeginAnimation(ScaleTransform.ScaleXProperty, scaleAnimation);
            //CanvasScaleTransform.BeginAnimation(ScaleTransform.ScaleYProperty, scaleAnimation);

            CanvasScaleTransform.CenterX = transformedMousePosition.X;
            CanvasScaleTransform.CenterY = transformedMousePosition.Y;

            CanvasScaleTransform.ScaleX = newScale;
            CanvasScaleTransform.ScaleY = newScale;
        }        
    }
}
